
package jason.jeditplugin;

import jason.asSemantics.Agent;
import jason.asSyntax.Plan;
import jason.mas2j.parser.TokenMgrError;

import java.io.StringReader;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.text.Position;
import javax.swing.tree.DefaultMutableTreeNode;

import org.gjt.sp.jedit.Buffer;

import sidekick.Asset;
import sidekick.SideKickParsedData;
import errorlist.DefaultErrorSource;
import errorlist.ErrorSource;

public class AgentSpeakSideKickParser extends sidekick.SideKickParser {
	public static final String ID = "asl";
	
	SideKickParsedData pd = null;
	
	public AgentSpeakSideKickParser() {
		super(ID);
	}
	
	public SideKickParsedData parse(Buffer buf, DefaultErrorSource errorSource) {
		String text;
		try {
			buf.readLock();
			text = buf.getText(0, buf.getLength());
		} finally {
			buf.readUnlock();
		}
		
		try {
			jason.asSyntax.parser.as2j parser = new jason.asSyntax.parser.as2j(new StringReader(text));
			
			Agent ag = new Agent();
			ag.initAg();
			ag.setSideKick(true);
			ag.setASLSrc(buf.getPath());
			parser.agent(ag);
			
			// create nodes 
			pd = new SideKickParsedData(buf.getName());
			for(Plan p : ag.getPL()) {
				DefaultMutableTreeNode node = new PlanAsset(p, buf).createTreeNode();
				pd.root.add(node);
			}
		} catch (jason.asSyntax.parser.ParseException ex) {
			addError(ex, errorSource, buf);
		} catch (jason.mas2j.parser.TokenMgrError e) {
			JasonProjectSideKickParser.addError(e.getMessage(), errorSource, buf);
		} catch (jason.asSyntax.parser.TokenMgrError e) {
			JasonProjectSideKickParser.addError(e.getMessage(), errorSource, buf);
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return pd;
	}
	
	public static void addError(jason.asSyntax.parser.ParseException e, DefaultErrorSource errorSource, Buffer buf) {
		if (e.currentToken == null) {
			JasonProjectSideKickParser.addError(e.getMessage(), null, 0, 0, e.isIgnoreSubsequentMessages(), errorSource, buf);
		} else {
			JasonProjectSideKickParser.addError(e.getMessage(), e.currentToken.beginLine, e.currentToken.beginColumn, e.currentToken.endColumn, e.isIgnoreSubsequentMessages(), errorSource, buf);
		}
	}
	
	public String toString() {
		return ID;
	}
	
	private static Icon PLAN_ICON;
	
	class PlanAsset extends Asset {
		
		private Plan plan;
		
		public PlanAsset(Plan p, Buffer buf) {
			//super(((p.getLabel() == null) ? "" : "@" + p.getLabel() + " ")    + p.getTriggerEvent());
			super(p.getTrigger().toString());
			this.plan = p;
			this.start = toPos(buf, p.getSrcInfo().getBeginSrcLine());
			this.end = toPos(buf, p.getSrcInfo().getEndSrcLine());
		}
		
		public Icon getIcon() {
			if (PLAN_ICON == null) {
				PLAN_ICON = new ImageIcon(AgentSpeakSideKickParser.class.getResource("/images/plan.png"));
			}
			return PLAN_ICON;
		}
		
		public String getShortString() {
			return name;
		}
		
		public String getLongString() {
			return plan.toASString();
		}
		
		private Position toPos(Buffer buffer, int line) {
			if (line >= buffer.getLineCount()) return buffer.createPosition(buffer.getLength() - 1);
			try {
				int offset = buffer.getLineStartOffset(line - 1);
				if (offset >= buffer.getLength()) {
					return buffer.createPosition(buffer.getLength() - 1);
				}
				return buffer.createPosition(offset);
			} catch (ArrayIndexOutOfBoundsException e) {
				return buffer.createPosition(buffer.getLength() - 1);
			}
		}
		
		public DefaultMutableTreeNode createTreeNode() {
			return new DefaultMutableTreeNode(this, true);
		}
	}
}
